#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_changevalue_ = 0;

    m_bThres = ui->horizontalSlider_threshold->value();
    ui->label_threshold->setText(QString::number(m_bThres));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event)
    showImage(g_showImage);
}

void MainWindow::on_btn_ReadImage_clicked()
{
    QString oldpath;
    if (lastPath.isEmpty())
    {
        oldpath = "../";
    }
    else
    {
        oldpath = lastPath + "/";
    }
    QString path = QFileDialog::getOpenFileName(
                this,
                "打开",
                oldpath,
                "Images(*.bmp *.png *.jpg)");
    if (!path.isEmpty())
    {
        lastPath = PathxtoPath(path);
        loadImage(path);
        if (!m_image.isNull())
        {
            m_changevalue_ = 3;
            ui->spinBox_outWidth->setValue(m_image.width());
            ui->spinBox_outHeight->setValue(m_image.height());
            m_changevalue_ = 0;
        }
    }
}

void MainWindow::loadImage(QString path)
{
    if (m_image.load(path))
    {
        ui->lineEdit_imagePath->setText(path);
        QImage image = m_image.copy();
        if (ui->comboBox_showMode->currentIndex() == 1)
        {
            image = grayScaleImg(image);
        }
        else if (ui->comboBox_showMode->currentIndex() == 2)
        {
            image = grayScaleImg(image);
            image = thresholdImg(image);
        }
        showImage(image);
    }
    else
    {
        Inform("图片打开失败！");
    }
}

void MainWindow::showImage(QImage image)
{
    if (image.isNull())
    {
        ui->label_ImageShow->setText("当前无图像");
        return ;
    }
    ui->label_width->setText(QString::number(m_image.width()));
    ui->label_height->setText(QString::number(m_image.height()));
    if (ui->comboBox_scale->currentIndex() == 1)
    {
        image = image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
    }
    g_showImage = image;
    ui->label_ImageShow->update();
    //qDebug() << "oldimage width:" << image.width() << ", height:" << image.height();
    //int showx = 0, showy = 0, showwidth = 0, showheight = 0;
    //qDebug() << "label width:" << ui->label_ImageShow->width() << ", height:" << ui->label_ImageShow->height();
    //QImage showimage = ScaleImage2Label(image, ui->label_ImageShow, showx, showy, showwidth, showheight);
    //qDebug() << "showimage width:" << showimage.width() << ", height:" << showimage.height();
    //ui->label_ImageShow->setPixmap(QPixmap::fromImage(showimage));
    //ui->label_ImageShow->setVisible(true);
}

QImage MainWindow::grayScaleImg(QImage image)
{
    int nwidth = image.width();
    int nheight = image.height();
    QImage grayImg(nwidth, nheight, QImage::Format_Grayscale8);
    if (image.isNull())
    {
        return grayImg;
    }
    //QImage* grayImg = new QImage(nwidth, nheight, QImage::Format_Grayscale8);

    QRgb rgbVal = 0;
    int grayVal = 0;

    for (int x = 0; x < nwidth; x++)
    {
        for (int y = 0; y < nheight; y++)
        {
            rgbVal = image.pixel(x, y);
            grayVal = qGray(rgbVal);
            grayImg.setPixel(x, y, QColor(grayVal, grayVal, grayVal).rgb());
        }
    }
    return grayImg;
}

QImage MainWindow::thresholdImg(QImage image)
{
    QImage outImg(image.width(), image.height(), QImage::Format_Mono);
    if (image.isNull())
    {
        return outImg;
    }
    uint bt;
    //QColor oldColor;
    QColor oldcolor;
    for (int i = 0; i < image.width(); i++)
    {
        for (int j = 0; j < image.height(); j++)
        {
            oldcolor = QColor(image.pixel(i, j));
            if (oldcolor.red() > m_bThres)
            {
                bt = 1;
            }
            else
            {
                bt = 0;
            }
            outImg.setPixel(i, j, bt);
        }
    }
    return outImg;
}

void MainWindow::Inform(QString strdata)
{
    QMessageBox m_r(this);
    m_r.setWindowTitle("提示");
    m_r.setText(strdata);
    m_r.exec();
}

void MainWindow::on_comboBox_showMode_currentIndexChanged(int index)
{
    QImage image = m_image.copy();
    if (index == 1)
    {
        image = grayScaleImg(image);
    }
    else if (index == 2)
    {
        image = grayScaleImg(image);
        image = thresholdImg(image);
    }
    showImage(image);
}

///
/// \brief 单张导出
///
void MainWindow::on_btn_outputHex_clicked()
{
    if (m_image.isNull())
    {
        Inform("当前无图像");
        return ;
    }
    //char *datas;
    QImage image = m_image.copy();
    image = image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
    image = grayScaleImg(image);
    //image = thresholdImg(image);
    int num = image.width() * image.height();
    if (num <= 0)
    {
        Inform("导出错误，图像无像素");
        return ;
    }
    char datas[(image.width() * image.height() + 7) / 8];
    if (!imageToHEX(image, datas))
    {
        Inform("导出错误，转换HEX错误");
        return ;
    }
    QByteArray bytedata = QByteArray::fromRawData(datas, (image.width() * image.height() + 7) / 8);
    //qDebug() << "bytedata length:" << bytedata.length();   // 680
    //qDebug() << bytedata;
    if (bytedata.isEmpty())
    {
        Inform("导出错误！无数据！");
        return ;
    }
    if (ui->checkBox_addFileHeader->isChecked())
    {
        bytedata = AddFileHeader(1, bytedata.length()) + bytedata;
    }
    QString oldpath;
    if (lastPath.isEmpty())
    {
        oldpath = "../";
    }
    else
    {
        oldpath = lastPath + "/";
    }
    QString path = QFileDialog::getSaveFileName(
                this, "导出模板", oldpath, "BIN(*.bin)");
    if (!path.isEmpty())
    {
        lastPath = PathxtoPath(path);
        if (SaveBin(path, bytedata))
        {
            Inform("保存成功");
        }
        else
        {
            Inform("保存失败");
        }
    }
}

/*
 * 文件头一共16个字节
 * XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
 * [0-1]	首固定2字节:0xDA 0xE0  (Danpe0)
 * [2]		版本1字节
 * [3]		帧率1字节
 * [4-5]	宽2字节
 * [6-7]	高2字节
 * [8-10]	图片数量3字节
 * [11-14]	文件大小4字节
 * [15]		视频名的编码格式：00:无视频名，后面即为图像内容  01:Acsii  02:GBK   03:Unicode  04:UTF-8
 *
 * 然后是80(16*5)字节的文件名内容
 * 如果是GBK或者Unicode可以支持40个汉字名，如果是UTF-8可以存储26个汉字名
*/

///
/// \brief 保存为bin文件
/// \param path
/// \param data
/// \return
///
bool MainWindow::SaveBin(QString path, QByteArray data)
{
    if (data.isEmpty())
    {
        return false;
    }
    QFile file(path);
    if (!file.open(QFile::WriteOnly | QFile::Truncate))
    {
        file.close();
        return false;
    }
    file.write(data);
    file.close();

    return true;
}

///
/// \brief 批量路径
///
void MainWindow::on_btn_allImagePath_clicked()
{
    QString oldpath;
    if (lastPath.isEmpty())
    {
        oldpath = "../";
    }
    else
    {
        oldpath = lastPath + "/";
    }
    QString path = QFileDialog::getExistingDirectory(
                this, "选择批量文件路径", oldpath);
    if (!path.isEmpty())
    {
        lastPath = path;
        m_allimagepath = path;
        ui->lineEdit_imagePath->setText(path);
    }
}

///
/// \brief 检索
///
void MainWindow::on_btn_serarch_clicked()
{
    int firstnum = ui->spinBox_firstNum->value();
    int endnum = ui->spinBox_endNum->value();
    if (endnum < firstnum)
    {
        Inform("请输入有效数字");
        return ;
    }
    QString path;
    ui->listWidget_imagesName->clear();
    for (int i = firstnum; i <= endnum; i++)
    {
        path = m_allimagepath + "/" + ui->lineEdit_inputsNameA->text() + QString::number(i) + ui->lineEdit_inputsNameB->text();
        //qDebug() << "path:" << path;
        if (isFileExist(path))
        {
            ui->listWidget_imagesName->addItem(ui->lineEdit_inputsNameA->text() + QString::number(i) + ui->lineEdit_inputsNameB->text());
        }
    }
    //ui->listWidget_imagesName->update();
}

///
/// \brief 判断是否有此文件
/// \param path
/// \return
///
bool MainWindow::isFileExist(QString path)
{
    QFileInfo fileinfo(path);
    return fileinfo.isFile();
}

///
/// \brief 批量导出
///
void MainWindow::on_btn_allOutputHex_clicked()
{
    uint64_t successnum = 0;
    QByteArray bytedatas;
    for (int imagenum = 0; imagenum < ui->listWidget_imagesName->count(); imagenum++)
    {
        QString path = m_allimagepath + "/" + ui->listWidget_imagesName->item(imagenum)->text();
        //qDebug() << "path:" << path;
        QImage image(path);
        if (!image.isNull())
        {
            image = image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
            //qDebug() << "image open success";
            image = grayScaleImg(image);
            //image = thresholdImg(image);
            int num = image.width() * image.height();
            if (num <= 0)
            {
                qDebug() << "image pet err";
                continue;
            }
            char datas[(image.width() * image.height() + 7) / 8];
            if (!imageToHEX(image, datas))
            {
                qDebug() << "image to hex fail.";
                continue;
            }
            QByteArray bytedata = QByteArray::fromRawData(datas, (image.width() * image.height() + 7) / 8);
            //qDebug() << "bytedata length:" << bytedata.length();   // 680
            //qDebug() << bytedata;
            if (bytedata.isEmpty())
            {
                //qDebug() << "bytedata isempty";
                continue;
            }
            else
            {
                successnum++;
                bytedatas += bytedata;
            }
        }
    }
    if (bytedatas.isEmpty())
    {
        Inform("导出数据失败");
        return ;
    }
    if (ui->checkBox_addFileHeader->isChecked())   // 增加文件头
    {
        bytedatas = AddFileHeader(successnum, bytedatas.length()) + bytedatas;

//        char FileHeader[16];
//        FileHeader[0] = 0xDA;   // 固定两字节  0xDAE0
//        FileHeader[1] = 0xE0;
//        FileHeader[2] = 0x10;   // 版本       0.1版本
//        FileHeader[3] = ui->spinBox_frameRate->value();	// 帧率
//        uint16_t width, height;
//        width = ui->spinBox_outWidth->value();
//        height = ui->spinBox_outHeight->value();
//        FileHeader[4] = width & 0xFF;			// 宽度低位字节
//        FileHeader[5] = (width >> 8) & 0xFF;	// 宽度高位字节
//        FileHeader[6] = height & 0xFF;			// 高度低位字节
//        FileHeader[7] = (height >> 8) & 0xFF;	// 高度高位字节
//        FileHeader[8] = successnum & 0xFF;		// 图片数量
//        FileHeader[9] = (successnum >> 8) & 0xFF;
//        FileHeader[10] = (successnum >> 16) & 0xFF;
//        uint32_t length;
//        if (ui->checkBox_addFileName->isChecked())
//        {
//            length = bytedatas.length() + 96;
//            FileHeader[15] = 0x02;
//        }
//        else
//        {
//            length = bytedatas.length() + 16;
//            FileHeader[15] = 0x00;
//        }
//        FileHeader[11] = length & 0xFF;
//        FileHeader[12] = (length >> 8) & 0xFF;
//        FileHeader[13] = (length >> 16) & 0xFF;
//        FileHeader[14] = (length >> 24) & 0xFF;
//        if (ui->checkBox_addFileName->isChecked())
//        {
//            QString name = ui->lineEdit_fileName->text();
//            QByteArray bytename = name.toUtf8();
//            if (bytename.length() > 80)
//            {
//                bytename = bytename.left(80);
//            }
//            char zeo = 0x00;
//            //QByteArray bytezeo = QByteArray::fromRawData(&zeo, 1);
//            while (bytename.length() < 80)
//            {
//                bytename.append(zeo);
//            }
//            QByteArray BFileH = QByteArray::fromRawData(FileHeader, 16);
//            bytedatas = BFileH + bytename + bytedatas;
//        }
//        else
//        {
//            QByteArray BFileH = QByteArray::fromRawData(FileHeader, 16);
//            bytedatas = BFileH + bytedatas;
//        }
    }

    QString oldpath;
    if (lastPath.isEmpty())
    {
        oldpath = "../";
    }
    else
    {
        oldpath = lastPath + "/";
    }
    QString path = QFileDialog::getSaveFileName(
                this, "导出模板", oldpath, "BIN(*.bin)");
    if (!path.isEmpty())
    {
        //g_showImage.save(path);
        if (SaveBin(path, bytedatas))
        {
            Inform("保存成功");
        }
        else
        {
            Inform("保存失败");
        }
    }
}

QByteArray MainWindow::AddFileHeader(int num, int bytelength)
{
    char FileHeader[16];
    FileHeader[0] = 0xDA;   // 固定两字节  0xDAE0
    FileHeader[1] = 0xE0;
    FileHeader[2] = 0x10;   // 版本       0.1版本
    FileHeader[3] = ui->spinBox_frameRate->value();	// 帧率
    uint16_t width, height;
    width = ui->spinBox_outWidth->value();
    height = ui->spinBox_outHeight->value();
    FileHeader[4] = width & 0xFF;			// 宽度低位字节
    FileHeader[5] = (width >> 8) & 0xFF;	// 宽度高位字节
    FileHeader[6] = height & 0xFF;			// 高度低位字节
    FileHeader[7] = (height >> 8) & 0xFF;	// 高度高位字节
    FileHeader[8] = num & 0xFF;		// 图片数量
    FileHeader[9] = (num >> 8) & 0xFF;
    FileHeader[10] = (num >> 16) & 0xFF;
    uint32_t length;
    if (ui->checkBox_addFileName->isChecked())
    {
        length = bytelength + 96;
        FileHeader[15] = 0x02;
    }
    else
    {
        length = bytelength + 16;
        FileHeader[15] = 0x00;
    }
    FileHeader[11] = length & 0xFF;
    FileHeader[12] = (length >> 8) & 0xFF;
    FileHeader[13] = (length >> 16) & 0xFF;
    FileHeader[14] = (length >> 24) & 0xFF;
    if (ui->checkBox_addFileName->isChecked())
    {
        QString name = ui->lineEdit_fileName->text();
        QByteArray bytename = name.toUtf8();
        if (bytename.length() > 80)
        {
            bytename = bytename.left(80);
        }
        char zeo = 0x00;
        //QByteArray bytezeo = QByteArray::fromRawData(&zeo, 1);
        while (bytename.length() < 80)
        {
            bytename.append(zeo);
        }
        QByteArray BFileH = QByteArray::fromRawData(FileHeader, 16);
        return BFileH + bytename;
    }
    else
    {
        QByteArray BFileH = QByteArray::fromRawData(FileHeader, 16);
        return BFileH;
    }
}

bool MainWindow::imageToHEX(QImage image, char* datas)
{
    if (image.isNull())
    {
        qDebug() << "image to hex fail, image isnull";
        return false;
    }
    for (int i = 0; i < (image.width() * image.height() + 7) / 8; i++)
    {
        datas[i] = 0;
    }
    for (int i = 0; i < image.width(); i++)  // 85
    {
        for (int j = 0; j < image.height(); j++)   // 64
        {
            int num = i * image.height() + j;
            int bitnum = num % 8;
            uint8_t data = 0;
            if (image.pixelColor(i, j).red() > m_bThres)
            {
                data = 1;
            }
            datas[num / 8] |= data << (7 - bitnum);
        }
    }
    return true;
}

int MainWindow::getPixel(const QImage image, const int col, const int row)
{
    const char uMask = 0x80 >> (col % 8);
    return image.scanLine(row)[col / 8] & uMask ? 1 : 0;
}

void MainWindow::on_listWidget_imagesName_itemClicked(QListWidgetItem *item)
{
    QString path = m_allimagepath + "/" + item->text();
    loadImage(path);
}

void MainWindow::on_horizontalSlider_threshold_valueChanged(int value)
{
    m_bThres = value;
    ui->label_threshold->setText(QString::number(m_bThres));
    if (m_image.isNull())
    {
        return ;
    }
    if (ui->comboBox_showMode->currentIndex() == 2)
    {
        QImage image;
        if (ui->comboBox_scale->currentIndex() == 0)
        {
            image = m_image.copy();
        }
        else
        {
            image = m_image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
        }
        image = grayScaleImg(image);
        image = thresholdImg(image);
        showImage(image);
    }
}

void MainWindow::on_btn_saveImage_clicked()
{
    if (g_showImage.isNull())
    {
        Inform("当前无图像！");
        return ;
    }
    QString oldpath;
    if (lastPath.isEmpty())
    {
        oldpath = "../";
    }
    else
    {
        oldpath = lastPath + "/";
    }
    QString path = QFileDialog::getSaveFileName(
                this, "导出模板", oldpath, "BMP(*.bmp);;JPG(*.jpg);;PNG(*.png)");
    if (!path.isEmpty())
    {
        lastPath = PathxtoPath(path);
        g_showImage.save(path);
    }
}

///
/// \brief 比例转换
/// \param x2
/// \param x1
/// \param y1
/// \return
///
int MainWindow::ProportionConversion(int x2, int x1, int y1)
{
    int y2;
    double dx2 = x2, dx1 = x1, dy1 = y1;
    y2 = (dx2 * dy1) / dx1;
    return y2;
}

///
/// \brief MainWindow::导出宽度改变
/// \param arg1
///
void MainWindow::on_spinBox_outWidth_valueChanged(int arg1)
{
    if (ui->checkBox_lockWidthHeight->isChecked())
    {
        if (m_changevalue_ == 0)
        {
            m_changevalue_ = 1;
            if (g_showImage.isNull())
            {
                ui->spinBox_outHeight->setValue(arg1);
            }
            else
            {
                ui->spinBox_outHeight->setValue(ProportionConversion(arg1, m_image.width(), m_image.height()));
            }
            if (ui->comboBox_scale->currentIndex() == 1)
            {
                showImage(m_image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value()));
            }
            m_changevalue_ = 0;
        }
    }
    if (ui->comboBox_scale->currentIndex() == 1)
    {
        QImage image = m_image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
        if (ui->comboBox_showMode->currentIndex() == 1)
        {
            image = grayScaleImg(image);
        }
        else if (ui->comboBox_showMode->currentIndex() == 2)
        {
            image = grayScaleImg(image);
            image = thresholdImg(image);
        }
        showImage(image);
    }
}

///
/// \brief 导出高度改变
/// \param arg1
///
void MainWindow::on_spinBox_outHeight_valueChanged(int arg1)
{
    if (ui->checkBox_lockWidthHeight->isChecked())
    {
        if (m_changevalue_ == 0)
        {
            m_changevalue_ = 2;
            if (g_showImage.isNull())
            {
                ui->spinBox_outWidth->setValue(arg1);
            }
            else
            {
                ui->spinBox_outWidth->setValue(ProportionConversion(arg1, m_image.height(), m_image.width()));
            }
            m_changevalue_ = 0;
        }
    }
    if (ui->comboBox_scale->currentIndex() == 1)
    {
        QImage image = m_image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
        if (ui->comboBox_showMode->currentIndex() == 1)
        {
            image = grayScaleImg(image);
        }
        else if (ui->comboBox_showMode->currentIndex() == 2)
        {
            image = grayScaleImg(image);
            image = thresholdImg(image);
        }
        showImage(image);
    }
}

void MainWindow::on_checkBox_lockWidthHeight_stateChanged(int arg1)
{
    if (arg1 == Qt::Checked)
    {
        if (g_showImage.isNull())
        {
            ui->spinBox_outHeight->setValue(ui->spinBox_outWidth->value());
        }
        else
        {
            ui->spinBox_outHeight->setValue(ProportionConversion(ui->spinBox_outWidth->value(), m_image.width(), m_image.height()));
            if (ui->comboBox_scale->currentIndex() == 1)
            {
                QImage image = m_image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
                if (ui->comboBox_showMode->currentIndex() == 1)
                {
                 image = grayScaleImg(image);
                }
                else if (ui->comboBox_showMode->currentIndex() == 2)
                {
                    image = grayScaleImg(image);
                    image = thresholdImg(image);
                }
                showImage(image);
            }
        }
    }
}

void MainWindow::on_comboBox_scale_currentIndexChanged(int index)
{
    if (index == 0)		// 原图尺寸
    {
        QImage image = m_image.copy();
        if (ui->comboBox_showMode->currentIndex() == 1)
        {
            image = grayScaleImg(image);
        }
        else if (ui->comboBox_showMode->currentIndex() == 2)
        {
            image = grayScaleImg(image);
            image = thresholdImg(image);
        }
        showImage(image);
    }
    else if (index == 1)  // 导出尺寸
    {
        QImage image = m_image.scaled(ui->spinBox_outWidth->value(), ui->spinBox_outHeight->value());
        if (ui->comboBox_showMode->currentIndex() == 1)
        {
            image = grayScaleImg(image);
        }
        else if (ui->comboBox_showMode->currentIndex() == 2)
        {
            image = grayScaleImg(image);
            image = thresholdImg(image);
        }
        showImage(image);
    }
}
